﻿using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;

namespace FastDFS.Client
{
    internal static class ClientGlobal
    {
        /// <summary>
        /// millisecond
        /// </summary>
        public static int ConnectTimeout { get; private set; } = 5 * 1000;

        /// <summary>
        /// millisecond
        /// </summary>
        public static int NetworkTimeout { get; private set; } = 30 * 1000;

        public static string Charset { get; private set; } = "ISO8859-1";

        public static int TrackerHttpPort { get; private set; } = 22122;

        public static bool IsAntiStealToken { get; private set; } = false;

        public static string SecretKey { get; private set; } = "";

        public static TrackerGroup TrackerGroup { get; private set; }

        public static bool EnableClientPool = false;

        /// <summary>
        /// construct TcpClient object
        /// </summary>
        /// <param name="ipAddr">ip address or hostname</param>
        /// <param name="port">port number</param>
        /// <returns>connected TcpClient object</returns>
        public static async Task<TcpClient> GetSocketAsync(string ipAddr, int port)
        {
            TcpClient sock = new TcpClient();
            await sock.ConnectAsync(ipAddr, port);
            return sock;
        }
        /// <summary>
        /// construct TcpClient object
        /// </summary>
        /// <param name="addr">IPEndPoint object, including ip address and port</param>
        /// <returns>connected TcpClient object</returns>
        public static async Task<TcpClient> GetSocketAsync(IPEndPoint addr)
        {
            return await GetSocketAsync(addr.Address.ToString(), addr.Port);
        }

        public static bool Close(TcpClient client)
        {
            if (EnableClientPool) return false;

            if (client == null) return true;
            try
            {
                ProtoCommon.CloseSocket(client);
            }
            catch
            {
                // ignore
            }
            return true;
        }

        public static void Init(string confFilename)
        {
            IniFileReader iniReader;
            string[] szTrackerServers;
            string[] parts;

            iniReader = new IniFileReader(confFilename);

            ConnectTimeout = iniReader.GetIntValue("connect_timeout", 5);
            if (ConnectTimeout < 0)
            {
                ConnectTimeout = 5;
            }
            ConnectTimeout *= 1000; //millisecond

            NetworkTimeout = iniReader.GetIntValue("network_timeout", 30);
            if (NetworkTimeout < 0)
            {
                NetworkTimeout = 30;
            }
            NetworkTimeout *= 1000; //millisecond

            Charset = iniReader.GetStrValue("charset");
            if (string.IsNullOrEmpty(Charset))
            {
                Charset = "ISO8859-1";
            }

            szTrackerServers = iniReader.GetValues("tracker_server");
            if (szTrackerServers == null)
            {
                throw new FdfsException("item \"tracker_server\" in " + confFilename + " not found");
            }

            IPEndPoint[] trackerServers = new IPEndPoint[szTrackerServers.Length];
            for (int i = 0; i < szTrackerServers.Length; i++)
            {
                parts = szTrackerServers[i].Split("\\:".ToCharArray(), 2);
                if (parts.Length != 2)
                {
                    throw new FdfsException("the value of item \"tracker_server\" is invalid, the correct format is host:port");
                }

                trackerServers[i] = new IPEndPoint(IPAddress.Parse(parts[0].Replace("\0", "").Trim()), int.Parse(parts[1].Replace("\0", "").Trim()));
            }
            TrackerGroup = new TrackerGroup(trackerServers);

            TrackerHttpPort = iniReader.GetIntValue("http.tracker_http_port", 80);
            IsAntiStealToken = iniReader.GetBoolValue("http.anti_steal_token", false);
            if (IsAntiStealToken)
            {
                SecretKey = iniReader.GetStrValue("http.secret_key");
            }
        }
    }
}
